package com.dmy.chat.server.netty;

import com.dmy.chat.config.ChatServerConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Optional;

/**
 * create by huahuadelei for 2020/1/4
 */
public class ChatNettyServer implements Closeable {
    private final Logger logger = LoggerFactory.getLogger(ChatNettyServer.class);
    private static ChatNettyServer instance = null;

    private ChatNettyServer() {
    }

    public static ChatNettyServer getInstance(ChatServerConfig config) {
        if (instance == null) {
            synchronized (ChatNettyServer.class) {
                if (instance == null) {
                    instance = new ChatNettyServer(config.getPort(), config.getWsUrl());
                }
            }
        }
        return instance;
    }

    private final static int DEFAULT_PORT = 8601;

    private Integer port;
    private String wsUrl;

    private EventLoopGroup boss;
    private EventLoopGroup work;

    private ServerBootstrap server;

    private ChatNettyServer(Integer port, String wsUrl) {
        this.port = Optional.ofNullable(port).orElse(DEFAULT_PORT);
        this.wsUrl = wsUrl;
    }

    public void start() throws InterruptedException {
        boss = new NioEventLoopGroup(1);
        work = new NioEventLoopGroup();
        server = new ServerBootstrap();
        server.group(boss, work)
                .channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.SO_BACKLOG, 128)
                .childHandler(new ChatChannelInitializer());
        ChannelFuture future = server.bind(new InetSocketAddress(port)).sync();
        logger.info("server started！listen ..." +port);
        future.channel().closeFuture();
    }

    @Override
    public void close() throws IOException {
        boss.shutdownGracefully();
        work.shutdownGracefully();
    }
}
